import {
	assign
} from 'lodash-es';

import {
	ResultEnum
} from '@/enums/httpEnum';
import {
	login
} from '@/services/api/auth';
import {
	decrypt as AESdecrypt,
	encrypt as AESencrypt,
	generatekey
} from '@/utils/AES';
import {
	getCache
} from '@/utils/catch';
import {
	getEnvValue
} from '@/utils/env';
import {
	decrypt,
	encrypt
} from '@/utils/jsencrypt';
import {
	router
} from '@/utils/router';
import {
	versionUpdate
} from '@/utils/version';
import store from '../../state/modules/auth.js';

import Request from './core/Request';
const BASE_URL = getEnvValue('VITE_BASE_URL');

const version = uni.getStorageSync('version') || '1.0.8';
const HEADER = {
	'content-type': 'application/json',
	version: version,
};

function createRequest() {
	return new Request({
		baseURL: BASE_URL,
		header: HEADER,
		custom: {
			auth: true,
		},
	});
}

const request = createRequest();

/**
 * 请求拦截器
 */
request.interceptors.request.use(
	(options) => {
		const {
			config
		} = options;
		if (config.custom?.auth) {

			if (!store.getters.isLogin) {
				return Promise.reject(options);
			}
			config.header = assign(config.header, {
				Authorization: `Bearer ${store.getters.getToken}`,
			});
		}

		const whiteList = [];
		if (config.header['content-type'] === 'application/json' && (config.method === 'POST' || config.method ===
				'PUT') && !whiteList.includes(config.url)) {
			const data = config.data ? (typeof config.data === 'object' ? JSON.stringify(config.data) : config
				.data) : JSON.stringify({});
			// 提交数据加密
			const finalParamObj = {
				encrypted: '',
				requestData: ''
			};
			// 生成aes秘钥
			const aseKey = generatekey(16);
			// rsa加密
			finalParamObj.encrypted = encrypt(aseKey);
			// aes加密
			finalParamObj.requestData = AESencrypt(data, aseKey);
			config.data = finalParamObj;
		}

		return options;
	},
	(options) => {

		return Promise.reject(options);
	},
);

/**
 * 响应拦截器
 */
// 是否更新APP的标记
let isUpdate = false;
// 是否正在刷新的标记
let isRefreshing = false;
// 重试队列，每一项将是一个待执行的函数形式
const requests = [];
request.interceptors.response.use(
	async (response) => {
			let {
				data
			} = response;
			if (data.encrypted) {
				const aesKey = decrypt(data.encrypted);
				data = JSON.parse(AESdecrypt(data.responseData, aesKey));
			}
			// 从解密的数据里面获取 code
			const {
				code
			} = data;
			if (code == ResultEnum.UPDATE) {
				if (!isUpdate) {
					isUpdate = true;
					// #ifdef APP-PLUS
					await versionUpdate(true);
					// #endif
				}
				return Promise.reject(data);
			}

			if (code === ResultEnum.SUCCESS) {
				return data;
			}

			// 刷新token
			if (code === ResultEnum.UNAUTHORIZED) {
				const {
					config
				} = response;
				if (!isRefreshing) {
					isRefreshing = true;
					const serialNumber = getCache('serialNumber');
					try {
						const loginData = await login({
							serialNumber
						});
						store.dispatch('setToken', loginData.token);
						isRefreshing = false;
						// 执行队列中的请求
						requests.forEach((cb) => cb(loginData.token));
						requests.splice(0, requests.length);
						return new Promise((resolve) => {
							config.header = assign(config.header, {
								Authorization: `Bearer ${loginData.token}`,
							});
							resolve(request.request(config));
						});
					} catch (error) {
						isRefreshing = false;
						store.dispatch('loginOut').then(() => {
							// token过期跳转到登录页 1秒后跳转
							setTimeout(() => {
								router.replaceAll('/pages/index/index');
							}, 1000);
						});
						return Promise.reject({
							message: '登录过期，请重新登录'
						});
					}
				} else {
					return new Promise((resolve) => {
						requests.push((token) => {
							config.header = assign(config.header, {
								Authorization: `Bearer ${token}`,
							});
							resolve(request.request(config));
						});
					});
				}
			}
			return Promise.reject(data);
		},
		(response) => {
			return Promise.reject(response.data);
		},
);

export {
	request
};